class ArbolHuffman:
    
    def __init__(self,caracter,frecuencia):
        self.caracter = caracter
        self.frecuencia = frecuencia
        self.izquierda = None
        self.derecha = None
        self.codigoBin = ""

    def crearPadre(self,arbolIzquierda,arbolDerecha):
        self.caracter = arbolIzquierda.caracter + "," + arbolDerecha.caracter
        self.frecuencia = arbolIzquierda.frecuencia + arbolDerecha.frecuencia
        self.izquierda = arbolIzquierda
        self.derecha = arbolDerecha
        self.izquierda.codigoBin = "0"
        self.derecha.codigoBin = "1"
        self.codigoBin = ""

    def crearHijoDer(self,caracter):
        self.derecha=ArbolHuffman(caracter,0)
        self.derecha.codigoBin="1"

    def crearHijoIzq(self,caracter):
        self.izquierda=ArbolHuffman(caracter,0)
        self.izquierda.codigoBin="0"

    def generarArbolPartirLista(self,listaDelArbol):
        arbolIz=ArbolHuffman(listaDelArbol[0][0],listaDelArbol[0][1])
        arbolDe=ArbolHuffman(listaDelArbol[1][0],listaDelArbol[1][1])
        arbolPa=ArbolHuffman("",0)
        arbolPa.crearPadre(arbolIz,arbolDe)
        listaDeArboles=[arbolPa]
        cont=2
        while True:
            try:
                arbolPa=listaDeArboles[0]
                if(arbolPa.frecuencia>=listaDelArbol[cont][1]):
                    if(arbolPa.frecuencia>listaDelArbol[cont+1][1]):
                        arbolIz=ArbolHuffman(listaDelArbol[cont][0],listaDelArbol[cont][1])
                        arbolDe=ArbolHuffman(listaDelArbol[cont+1][0],listaDelArbol[cont+1][1])
                        arbolPa=ArbolHuffman("",0)
                        arbolPa.crearPadre(arbolIz,arbolDe)
                        listaDeArboles.append(arbolPa)
                        cont=cont+2
                    else:
                        arbolIz=arbolPa
                        arbolDe=ArbolHuffman(listaDelArbol[cont][0],listaDelArbol[cont][1])
                        arbolPa=ArbolHuffman("",0)
                        arbolPa.crearPadre(arbolIz,arbolDe)
                        listaDeArboles.append(arbolPa)
                        listaDeArboles.remove(listaDeArboles[0])
                        cont=cont+1
                else:
                    try:
                        arbolPaAlt=listaDeArboles[1]
                        if(arbolPaAlt.frecuencia>listaDelArbol[cont][1]):
                            arbolIz=arbolPa
                            arbolDe=ArbolHuffman(listaDelArbol[cont][0],listaDelArbol[cont][1])
                            arbolPa=ArbolHuffman("",0)
                            arbolPa.crearPadre(arbolIz,arbolDe)
                            listaDeArboles.append(arbolPa)
                            listaDeArboles.remove(listaDeArboles[0])
                            cont=cont+1
                        else:
                            arbolIz=arbolPa
                            arbolDe=arbolPaAlt
                            arbolPa=ArbolHuffman("",0)
                            arbolPa.crearPadre(arbolIz,arbolDe)
                            listaDeArboles.append(arbolPa)
                            listaDeArboles.remove(listaDeArboles[0])
                            listaDeArboles.remove(listaDeArboles[0])
                    except:
                        arbolIz=arbolPa
                        arbolDe=ArbolHuffman(listaDelArbol[cont][0],listaDelArbol[cont][1])
                        arbolPa=ArbolHuffman("",0)
                        arbolPa.crearPadre(arbolIz,arbolDe)
                        listaDeArboles.append(arbolPa)
                        listaDeArboles.remove(listaDeArboles[0])
                        cont=cont+1
                        print("sali")            
            except:
                break
        if(cont!=len(listaDelArbol)):
            arbolPa=listaDeArboles[0]
            arbolIz=arbolPa
            arbolDe=ArbolHuffman(listaDelArbol[cont][0],listaDelArbol[cont][1])
            arbolPa=ArbolHuffman("",0)
            arbolPa.crearPadre(arbolIz,arbolDe)
            listaDeArboles.append(arbolPa)
            listaDeArboles.remove(listaDeArboles[0])
        while(len(listaDeArboles)>1):
            arbolIz=listaDeArboles[0]
            arbolDe=listaDeArboles[1]
            arbolPa=ArbolHuffman("",0)
            arbolPa.crearPadre(arbolIz,arbolDe)
            listaDeArboles.append(arbolPa)
            listaDeArboles.remove(listaDeArboles[0])
            listaDeArboles.remove(listaDeArboles[0])                                    
        return listaDeArboles[0]                    

    def generarBinario(self,caracter):
        if self.caracter != caracter:
            if self.izquierda!=None:
                try:
                    return self.codigoBin + self.izquierda.generarBinario(caracter)
                except TypeError:
                    pass
            if self.derecha!=None:
                try:
                    return self.codigoBin + self.derecha.generarBinario(caracter)
                except TypeError:
                    pass
        else:
            return self.codigoBin

    def generarDiccionarioBinario(self,listaDelArbol,arbolFinal):
        dic={}
        for i in listaDelArbol:
            dic[i[0]]=arbolFinal.generarBinario(i[0])
        print(dic)
        return dic

    def generarLetras(self,escritor,listaBinaria):
        escritoBin=""
        temporal=""
        caracteresDesc=""
        for i in listaBinaria:
            if(i.isnumeric()==True):
                escritoBin=escritoBin+i
                print("x")
            else:
                print(i)
                temporal=bin(ord(i))
                listaMinima=temporal.split("0b")
                temporal=listaMinima[1]
                print(temporal)
                while(len(temporal)<7):
                    temporal="0"+temporal
                    print(temporal)
                escritoBin=escritoBin+temporal
                
        arbolAlt=ArbolHuffman("",0)
        arbolAlt.caracter=self.caracter
        arbolAlt.frecuencia=self.frecuencia
        arbolAlt.izquierda=self.izquierda
        arbolAlt.derecha=self.derecha
        arbolAlt.codigoBin=self.codigoBin
        sobra=""
        for i in escritoBin:
            if(i=="1"):
                arbolAlt=arbolAlt.derecha
                sobra="1"
                if(arbolAlt.derecha==None):
                    caracteresDesc=caracteresDesc+arbolAlt.caracter
                    arbolAlt.caracter=self.caracter
                    arbolAlt.frecuencia=self.frecuencia
                    arbolAlt.izquierda=self.izquierda
                    arbolAlt.derecha=self.derecha
                    arbolAlt.codigoBin=self.codigoBin
                    sobra=""
            else:
                arbolAlt=arbolAlt.izquierda
                sobra="0"
                if(arbolAlt.derecha==None):
                    caracteresDesc=caracteresDesc+arbolAlt.caracter
                    arbolAlt.caracter=self.caracter
                    arbolAlt.frecuencia=self.frecuencia
                    arbolAlt.izquierda=self.izquierda
                    arbolAlt.derecha=self.derecha
                    arbolAlt.codigoBin=self.codigoBin
                    sobra=""
        escritor.write(caracteresDesc)
        return sobra
                
    def escribeArbolDer(self,escritor):
        if self.caracter!=None:
            if(len(self.caracter)==1):
                escritor.write(self.caracter)
            escritor.write(self.codigoBin)
            if self.derecha!=None:
                self.derecha.escribeArbolDer(escritor)
            if self.izquierda!=None:
                self.izquierda.escribeArbolDer(escritor)

    def generarArbolDesdeArchivo(self,lector,arbolPadre):
        caracterRecibido=lector.read(1)
        if(caracterRecibido.isnumeric()==False):
            letra=caracterRecibido
            numero=lector.read(1)
            arbolPadre.crearHijoDer(letra)
        else:
            arbolPadre.crearHijoDer("")
            arbolPadre.generarArbolDesdeArchivo(lector,arbolPadre.derecha)     
        caracterRecibido=lector.read(1)
        if(caracterRecibido.isnumeric()==False):
            letra=caracterRecibido
            numero=lector.read(1)
            arbolPadre.crearHijoIzq(letra)
        else:
            arbolPadre.crearHijoIzq("")
            arbolPadre.generarArbolDesdeArchivo(lector,arbolPadre.izquierda)            
        return arbolPadre
        
